#!/usr/bin/env node

const { spawn } = require('child_process');
const fs = require('fs');
const path = require('path');

// ------------------------------ 环境检测 ------------------------------
const IS_CI = process.env.CI === 'true' || process.env.GITHUB_ACTIONS || process.env.GITCODE_CI;

// 检查必要的环境变量 +16
if (!process.env.COMMANDLINE_TOOLS_HOME) {
  console.error('错误：COMMANDLINE_TOOLS_HOME环境变量未设置');
  console.error('请确保在CI/CD环境中正确设置此环境变量，或在本地环境中设置');
  process.exit(1);
}

// ------------------------------ 【配置管理】：支持本地和CI/CD环境 ------------------------------
const CONFIG = {
  // 本地环境配置
  LOCAL: {
    JAVA_HOME: "/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home",
    PROJECT_PATH: process.cwd(),
    HAP_OUTPUT_PATH: path.join(process.cwd(), "products", "default", "build", "default", "outputs", "default")
  },
  // CI/CD环境配置
  CI: {
    JAVA_HOME: process.env.JAVA_HOME || "$HOME/tools/java/17",  
    PROJECT_PATH: process.env.PROJECT_PATH || process.cwd(),
    HAP_OUTPUT_PATH: process.env.HAP_OUTPUT_PATH || path.join(process.cwd(), "products", "default", "build", "default", "outputs", "default")
  }
};

// 根据环境选择配置
const CURRENT_CONFIG = IS_CI ? CONFIG.CI : CONFIG.LOCAL;

// ------------------------------ 工具函数：执行Shell命令（封装spawn，实时输出日志） ------------------------------
function execCommand(command, args = [], options = {}) {
  return new Promise((resolve, reject) => {
    console.log(`[执行命令]：${command} ${args.join(' ')}`);
    
    // 确保环境变量被正确传递
    const child = spawn(command, args, {
      ...options,
      stdio: "inherit",  
      shell: true,
      env: { ...process.env }  // 显式传递所有环境变量
    });

    // 处理命令退出
    child.on('close', (code) => {
      if (code === 0) {
        resolve();
      } else {
        reject(new Error(`命令执行失败（退出码：${code}）：${command} ${args.join(' ')}`));
      }
    });

    // 处理命令错误（如命令不存在）
    child.on('error', (err) => {
      reject(new Error(`命令执行错误：${err.message}（命令：${command} ${args.join(' ')}）`));
    });
  });
}

// ------------------------------ 命令行工具检查功能 ------------------------------
async function checkCommandLineTools() {
  console.log("=== 检查命令行工具 ===");
  
  // 从环境变量获取工具路径
  const commandLineToolsHome = process.env.COMMANDLINE_TOOLS_HOME;
  
  if (!commandLineToolsHome) {
    console.error("错误：COMMANDLINE_TOOLS_HOME环境变量未设置");
    console.error("请确保工作流中已正确下载commandline-tools");
    process.exit(1);
  }
  
  if (!fs.existsSync(commandLineToolsHome)) {
    console.error("错误：命令行工具路径不存在:", commandLineToolsHome);
    console.error("请确保工作流中已正确下载commandline-tools");
    process.exit(1);
  }
  
  // 检查bin目录
  const binPath = path.join(commandLineToolsHome, "bin");
  if (!fs.existsSync(binPath)) {
    console.error("错误：命令行工具bin目录不存在:", binPath);
    process.exit(1);
  }
  
  // 设置环境变量
  process.env.PATH = `${binPath}:${process.env.PATH}`;
  console.log("命令行工具检查完成，路径:", commandLineToolsHome);
  console.log("bin目录已添加到PATH");
}

// ------------------------------ 【环境初始化】：合并所有初始化逻辑 ------------------------------
async function initEnvironment() {
  console.log("=== 初始化环境 ===");
  
  // 统一设置PATH（避免重复设置）
  const commandLineToolsHome = process.env.COMMANDLINE_TOOLS_HOME;
  const binPath = path.join(commandLineToolsHome, "bin");
  process.env.PATH = `${binPath}:${process.env.PATH}`;
  console.log("命令行工具PATH设置完成:", binPath);
  
  // 1. 初始化JDK
  console.log("--- 初始化JDK ---");
  if (IS_CI) {
    try {
      console.log("在CI/CD环境中检测JDK...");
      await execCommand("java", ["-version"]);
      console.log("JDK在CI/CD环境中可用");
    } catch (err) {
      console.log("尝试使用配置的JDK路径...");
      await init_JDK_core();
    }
  } else {
    await init_JDK_core();
  }
  
  // 2. 初始化ohpm
  console.log("--- 初始化ohpm ---");
  try {
    await execCommand("ohpm", ["-v"]);
    console.log("ohpm初始化成功");
  } catch (err) {
    if (IS_CI) {
      console.error("错误：ohpm未安装");
      console.error("提示：命令行工具包下载失败或ohpm未正确安装");
      console.error("请检查网络连接和工具包下载");
      process.exit(1);
    } else {
      console.error("错误：ohpm未安装，请手动安装后重新运行脚本");
      process.exit(1);
    }
  }
  
  // 3. 初始化hvigor
  console.log("--- 初始化hvigor ---");
  try {
    await execCommand("hvigorw", ["-v"]);
    console.log("hvigor初始化成功");
  } catch (err) {
    if (IS_CI) {
      console.error("错误：hvigor未安装");
      console.error("提示：命令行工具包下载失败或hvigor未正确安装");
      console.error("请检查网络连接和工具包下载");
      process.exit(1);
    } else {
      console.error("错误：hvigor未安装，请手动安装后重新运行脚本");
      process.exit(1);
    }
  }
  
  // 4. 设置SDK路径
  const sdkPath = path.join(commandLineToolsHome, 'sdk');
  await updateLocalProperties(sdkPath);
  console.log(`SDK路径设置完成: ${sdkPath}`);
  
  console.log("=== 环境初始化完成 ===");
}

// JDK核心初始化逻辑（提取出来避免重复）
async function init_JDK_core() {
  const javaExecPath = path.join(CURRENT_CONFIG.JAVA_HOME, "bin", "java");
  
  if (fs.existsSync(javaExecPath)) {
    console.log(`使用配置的JDK：${CURRENT_CONFIG.JAVA_HOME}`);
    process.env.JAVA_HOME = CURRENT_CONFIG.JAVA_HOME;
    process.env.PATH = `${CURRENT_CONFIG.JAVA_HOME}/bin:${process.env.PATH}`;
    await execCommand("java", ["-version"]);
    console.log("JDK初始化成功");
  } else {
    console.error("错误：JDK未安装或路径不正确");
    console.error(`期望路径：${CURRENT_CONFIG.JAVA_HOME}`);
    if (IS_CI) {
      console.error("在CI/CD环境中，请确保在YAML配置中正确安装了JDK");
    }
    process.exit(1);
  }
}

// ------------------------------ 自动管理local.properties ------------------------------
async function updateLocalProperties(sdkPath) {
  const localPropsPath = path.join(process.cwd(), 'local.properties');
  
  try {
    const content = `sdk.dir=${sdkPath}\n`;
    
    if (fs.existsSync(localPropsPath)) {
      const existingContent = fs.readFileSync(localPropsPath, 'utf8');
      if (existingContent.trim() === content.trim()) {
        console.log(`local.properties已正确配置: ${sdkPath}`);
        return;
      }
    }
    
    fs.writeFileSync(localPropsPath, content, 'utf8');
    console.log(`更新local.properties: ${sdkPath}`);
  } catch (err) {
    console.log(`local.properties管理失败: ${err.message}`);
  }
}

// ------------------------------ 【构建HAP】：整合issue.bat逻辑 ------------------------------
async function buildHAP() {
  console.log("=== 开始构建流程 ===");
  
  // 1. 清理所有issue相关配置
  console.log("=== 清理issue配置 ===");
  try {
    await execCommand("hvigorw", ["issueClear"], { cwd: CURRENT_CONFIG.PROJECT_PATH });
    console.log("issue配置清理完成");
  } catch (error) {
    console.error("issue配置清理失败:", error.message);
    process.exit(1);
  }
  
  // 2. 添加所有issue demos到构建配置（自动跳过黑名单和不完整的模块）
  console.log("=== 添加所有issue demos ===");
  try {
    await execCommand("hvigorw", ["issueAddAll"], { cwd: CURRENT_CONFIG.PROJECT_PATH });
    console.log("所有issue demos添加完成（已自动跳过有问题的模块）");
  } catch (error) {
    console.error("issue demos添加失败:", error.message);
    process.exit(1);
  }
  
  // 3. 安装依赖（使用issue.bat的registry配置）
  console.log("=== 开始安装依赖 ===");
  try {
    await execCommand("ohpm", [
      "install", "--all", 
      "--registry", "https://ohpm.openharmony.cn/ohpm/", 
      "--strict_ssl", "false"
    ], { cwd: CURRENT_CONFIG.PROJECT_PATH });
    console.log("依赖安装完成");
  } catch (error) {
    console.error("依赖安装失败:", error.message);
    process.exit(1);
  }
  
  // 4. 同步项目配置
  console.log("=== 同步项目配置 ===");
  try {
    await execCommand("hvigorw", ["--sync"], { cwd: CURRENT_CONFIG.PROJECT_PATH });
    console.log("项目配置同步完成");
  } catch (error) {
    console.error("项目配置同步失败:", error.message);
    process.exit(1);
  }
  
  // 5. 清理构建缓存
  console.log("=== 清理构建缓存 ===");
  try {
    await execCommand("hvigorw", ["clean", "--no-daemon"], { cwd: CURRENT_CONFIG.PROJECT_PATH });
    console.log("构建缓存清理完成");
  } catch (error) {
    console.error("构建缓存清理失败:", error.message);
    process.exit(1);
  }
  
  // 6. 构建HAP包（使用issue.bat的构建参数）
  console.log("=== 开始构建HAP包 ===");
  try {
    await execCommand("hvigorw", [
      "--mode", "module", 
      "-p", "module=default@default", 
      "-p", "product=default", 
      "assembleHap"
    ], { cwd: CURRENT_CONFIG.PROJECT_PATH });
    console.log("HAP包构建完成");
  } catch (error) {
    console.error("HAP包构建失败:", error.message);
    process.exit(1);
  }
  
  // 7. 验证输出
  console.log("=== 验证构建结果 ===");
  
  // 动态查找HAP文件
  const outputDir = CURRENT_CONFIG.HAP_OUTPUT_PATH;
  let hapFile = null;
  
  if (fs.existsSync(outputDir)) {
    const files = fs.readdirSync(outputDir);
    hapFile = files.find(file => file.endsWith('.hap'));
    
    if (hapFile) {
      const hapFilePath = path.join(outputDir, hapFile);
      const fileSize = fs.statSync(hapFilePath).size;
      console.log("HAP包构建成功！");
      console.log(`输出路径：${hapFilePath}`);
      console.log(`文件大小：${(fileSize / 1024 / 1024).toFixed(2)} MB`);
    } else {
      console.error(`错误：在目录 ${outputDir} 中未找到HAP文件`);
      process.exit(1);
    }
  } else {
    console.error(`错误：HAP包输出目录不存在（路径：${outputDir}）`);
    console.error("请检查构建日志，确认构建过程是否成功");
    process.exit(1);
  }
  
  console.log("=== 构建流程完成 ===");
}

// ------------------------------ 【代码质量检查】：codelinter集成 ------------------------------
async function runCodeQualityCheck() {
  console.log("=== 开始代码质量检查 ===");
  
  // PATH已在initEnvironment中设置，无需重复设置
  
  try {
    // 检查codelinter是否安装
    console.log("检查codelinter...");
    await execCommand("codelinter", ["--version"]);
    console.log("codelinter已安装");
  } catch (err) {
    console.log("codelinter调用失败，错误信息:", err.message);
    if (IS_CI) {
      console.log("codelinter未安装，可能是命令行工具包下载失败");
      console.log("跳过代码质量检查");
    } else {
      console.log("codelinter未安装，跳过代码质量检查");
    }
    return;
  }
  
  try {
    // 创建报告目录
    const reportDir = path.join(process.cwd(), 'reports', 'lint');
    if (!fs.existsSync(reportDir)) {
      fs.mkdirSync(reportDir, { recursive: true });
    }
    
    // 运行代码检查（添加增量检查参数 -i）
    console.log("执行代码质量检查...");
    
    const reportPath = path.join(reportDir, 'lint-report.json');
    await execCommand("codelinter", [process.cwd(), "-c", "code-linter.json5", "-f", "json", "-o", reportPath, "-i"]);
    console.log("代码质量检查完成");
    
    // 读取检查报告并分析结果
    if (fs.existsSync(reportPath)) {
      const report = fs.readFileSync(reportPath, 'utf8');
      if (report.trim()) {
        console.log(`检查报告已生成：${reportPath}`);
        
        // 解析JSON报告，检查是否有error级别的问题
        try {
          const reportData = JSON.parse(report);
          let hasErrors = false;
          
          // 检查报告中的错误 - 支持实际的报告格式
          if (Array.isArray(reportData)) {
            // 遍历每个文件的检查结果
            hasErrors = reportData.some(fileReport => {
              if (fileReport.messages && Array.isArray(fileReport.messages)) {
                return fileReport.messages.some(message => 
                  message.severity === 'error'
                );
              }
              return false;
            });
          } else if (reportData.issues && Array.isArray(reportData.issues)) {
            // 兼容其他可能的报告格式
            hasErrors = reportData.issues.some(issue => 
              issue.severity === 'error' || issue.level === 'error'
            );
          }
          console.log("=== 代码质量检查完整报告 ===");
          try {
            const formattedReport = JSON.stringify(JSON.parse(report), null, 2);
            console.log(formattedReport);
          } catch (e) {
            console.log("格式化失败，输出原始报告：");
            console.log(report);
          }
          
          if (hasErrors) {
            console.error("发现代码质量错误，构建终止");
            process.exit(1);
          } else {
            console.log("代码质量检查通过");
          }
        } catch (parseErr) {
          console.log("无法解析检查报告，但报告已生成");
        }
      } else {
        console.log("未发现代码质量问题");
      }
    }
    
  } catch (err) {
    console.error("代码质量检查失败，构建终止");
          console.log("详细报告请查看：reports/lint/lint-report.json");
    process.exit(1);
  }
}

// ------------------------------ 【主流程】：按顺序执行所有步骤 ------------------------------
async function main() {
  try {
    const startTime = Math.floor(Date.now() / 1000); // 开始时间（秒级）
    console.log("=== OpenHarmony应用构建流程开始 ===");
    console.log(`环境: ${IS_CI ? 'CI/CD' : '本地开发'}`);
    console.log(`项目路径: ${CURRENT_CONFIG.PROJECT_PATH}`);
    
    // 检查命令行参数
    const args = process.argv.slice(2);
    
    // 检查是否只运行代码质量检查
    if (args.length > 0 && args[0] === 'lint') {
      await runCodeQualityCheck();
      return;
    }
    
    // 1. 检查依赖安装
    await checkCommandLineTools();
    
    // 2. 初始化环境（JDK、ohpm、hvigor、SDK路径）
    await initEnvironment();
    
    // 3. 环境变量设置完成
    console.log("环境变量设置完成");
    
    // 执行代码质量检查和构建HAP
    await runCodeQualityCheck();
    await buildHAP();
    
    const endTime = Math.floor(Date.now() / 1000); // 结束时间（秒级）
    const elapsedTime = endTime - startTime; // 总耗时（秒）
    console.log(`=== 构建流程完成！总耗时：${elapsedTime}秒 ===`);
  } catch (err) {
    console.error(`=== 构建流程失败：${err.message} ===`);
    process.exit(1); // 非0退出码表示失败（符合Shell脚本的习惯）
  }
}

// ------------------------------ 模块导出 ------------------------------
module.exports = {
  // 导出工具函数
  execCommand,
  // 导出配置
  CONFIG,
  CURRENT_CONFIG,
  IS_CI
};

// ------------------------------ 执行主流程 ------------------------------
if (require.main === module) {
  main();
} 